home *** CD-ROM | disk | FTP | other *** search
/ BBS in a Box 3 / BBS in a box - Trilogy III.iso / Files / Prog / U-Z / VideoToolBox Folder / VideoToolboxSources / IsNan.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-02-23  |  3.9 KB  |  93 lines  |  [TEXT/KAHL]

  1. /* IsNan.c
  2. Fast, portable routines to check for IEEE transfinite numbers: INF and NAN. You
  3. should also look at the macro IsFinite() in VideoToolbox.h.
  4.  
  5. IsNan and IsInf assume that every NAN's most significant mantissa bit is set,
  6. which is apparently an informal convention supported by the Intel math chip and
  7. perhaps the Motorola math chip. The definition of a NAN in the Apple Numerics
  8. book only says that a NAN is distinguished from an INF by having a nonzero
  9. mantissa. Unfortunately, a strict test of this would require testing all 8
  10. bytes, and in fact the routines in Plaugher's The Standard C Library do exactly
  11. this. However, this seems wasteful since the 255 different NANs that can be
  12. specified by the one byte NAN type are obviously more than enough for most
  13. programs. Indeed, since the Motorola chip doesn't preserve NAN type, the number
  14. of NAN types is rather academic; a single NAN type seems to be plenty for most
  15. applications. While it is possible to assemble a NAN with zero type, which is
  16. preserved through 8881 operations, and which printf("%f") prints as NAN00, the
  17. SANE routines all seem to immediately convert the zero type NAN to type 4, so IsNan()
  18. does too.
  19.  
  20. The assert() tests referring to sizeof(double) are evaluated by the compiler, with no 
  21. runtime penalty.
  22.  
  23. HISTORY:
  24. 8/24/91 dgp    made compatible with THINK C 5.0.
  25. 12/23/91 dgp I replaced the #if statements by ordinary if statements, which are 
  26.     more readable and are allowed to use the sizeof() operator.
  27.     Note that most of the if statements will be evaluated and removed by the
  28.     compiler, with no runtime penalty.
  29. 12/23/91 dgp Wrote my own code to replace the SANE code since it's too slow.
  30.     This makes IsNan() about 5 times faster.
  31.     My code is based on the Apple Numerics Manual, 2nd edition. It says that
  32.     a number is a NAN iff the exponent is all ones and the fraction is nonzero.
  33.     I make a slight shortcut in checking only the top 15 bits of the fraction,
  34.     since that includes the byte that specifies the NAN type, on the premise
  35.     that all NANs that I will actually see in practice will have nonzero type.
  36.     My code handles the ordinary cases of 10 or 12 byte doubles. The weird
  37.     case of shorter doubles (which are unlikely since they run very slowly)
  38.     are detected by the assert() test at the beginning.
  39. 12/23/91 dgp Asked the THINK C compiler not to time this routine.
  40. 12/29/91 dgp Eliminated the need for Sane.h and Types.h. The sane stuff
  41.     now appears in its own file: Sane.c. 
  42.     Wrote IsInf().
  43.     Wrote a new macro definition, in VideoToolbox.h, for IsFinite(), 
  44.     that allows fast inline testing for whether a number is ok, i.e. neither 
  45.     NAN nor INF. 
  46. 1/14/92    dgp    Changed IsNan() to now return the type (1..255) of the NAN, or zero
  47.     if not a NAN. This will break programs that assume the true value is always 1,
  48.     e.g. nans+=IsNan(a);
  49.     Fixed IsInf() to correctly return sign of ±INF.
  50. 1/18/92    dgp    Rewrote routines, making them simpler, and always checking the most 
  51.     significant bit of the mantissa in testing for NAN.
  52. */
  53.  
  54. #include "VideoToolbox.h"
  55. #include <assert.h>
  56. #if THINK_C
  57.     #pragma options(!profile)    /* Attribute to the caller the time spent here. */
  58. #endif
  59. #define EXPONENT 0
  60. #define MANTISSA (1+(sizeof(double)-10)/sizeof(short))
  61.  
  62. int IsNan(double x)
  63. /* Returns x's NAN type (1...255) or zero if x is not a NAN. */
  64. /* If NaN type is zero, return 4, as do the Apple routines. */
  65. {
  66.     register short i;
  67.  
  68.     assert(sizeof(double)==10 || sizeof(double)==12);
  69.     if((((short *)&x)[EXPONENT] & 0x7FFF)==0x7FFF){        // either NAN or INF
  70.         i=((short *)&x)[MANTISSA] & 0x7FFF;
  71.         if(i==0)return 0;
  72.         i&=0xFF;
  73.         if(i!=0)return i;
  74.         else return 4;
  75.     } else return 0;
  76. }
  77.  
  78. int IsInf(double x)
  79. /* Returns -1 for -INF, 0 for not INF, and +1 for +INF. */
  80. {
  81.     register short i;
  82.  
  83.     assert(sizeof(double)==10 || sizeof(double)==12);
  84.     i=((short *)&x)[EXPONENT];
  85.     if((i & 0x7FFF)==0x7FFF){                            // either NAN or INF
  86.         if((((short *)&x)[MANTISSA] & 0x7FFF)==0){
  87.             if(i<0)return -1;                            // -INF
  88.             else return 1;                                // +INF
  89.         }
  90.     }
  91.     return 0;
  92. }
  93.